<template>
    <!-- 聊天界面下方的发送信息组件 -->
    <div class="send-panel">
        <div class="toolbar">
            <!-- 表情 -->
            <el-popover :visible="showEmojiPopover" trigger="click" placement="top" :teleported="false"
                @show="openPopover" @hide="closePopover"
                :popper-style="{ padding: '0px 10px 10px 10px', width: '490px' }">
                <template #default>
                    <el-tabs v-model="activeEmoji" @click.stop>
                        <el-tab-pane :label="emoji.name" :name="emoji.name" v-for="(emoji, index) in emojiList"
                            :key="index">
                            <div class="emoji-list" v-for="(emo, i) in emoji.list" :key="i">
                                <div class="emoji-item" @click="sendEmoji(emo)">
                                    {{ emo }}
                                </div>
                            </div>
                        </el-tab-pane>
                    </el-tabs>
                </template>
                <template #reference>
                    <div class="iconfont icon-chenggongbiaoqing" @click="showEmojiPopoverHandler"></div>
                </template>
            </el-popover>
            <!-- 文件 -->
            <el-upload ref="uploadRef" name="file" :show-file-list="false" :multiple="true"
                :limit="sysSetting.maxFileCount" :http-request="uploadFile" :on-exceed="fileCountExceed">
                <div class="iconfont icon-wenjianguanli"></div>
            </el-upload>
        </div>
        <div class="input-area" @drop="dropHandler" @dragover="dragOverHandler">
            <el-input id="msgInput" :rows="5" v-model="msgContent" type="textarea" resize="none" maxlength="500"
                show-word-limit spellcheck="false" input-style="background:#f5f5f5;border:none;"
                @keydown.enter="sendMessage" @paste="pasteFile"></el-input>
        </div>
        <!-- 发送按钮 -->
        <div class="send-btn-panel">
            <el-popover trigger="click" :hide-after="1500" placement="top-end" :teleported="false"
                @show="showSendMsgPopover" @hide="closePopover"
                :popper-style="{ padding: '5px', 'min-width': '0px', width: '120px' }">
                <template #default>
                    <span class="empty-msg">不能发送空白消息</span>
                </template>
                <template #reference>
                    <span class="send-btn" @click="sendMessage">发送(S)</span>
                </template>
            </el-popover>
        </div>
    </div>
    <SearchAdd ref="searchAddRef"></SearchAdd>
</template>

<script setup>
import { ref, reactive, getCurrentInstance, nextTick, watch } from "vue"
import { useRoute, useRouter } from "vue-router";
const { proxy } = getCurrentInstance();
const route = useRoute();
const router = useRouter();

import emojiList from "@/utils/emoji";

const props = defineProps({
    currentChatSession: {
        type: Object,
        default: {}
    },
});

// 选择的表情包分类
const activeEmoji = ref("情感");
const sendEmoji = (emoji) => {
    msgContent.value += emoji;
    showEmojiPopover.value = false;
    // 让输入框获得焦点
    nextTick(() => {
        let msgInput = document.getElementById("msgInput");
        msgInput.focus();
    });
};

const showEmojiPopoverHandler = () => {
    showEmojiPopover.value = true;
};

const openPopover = () => {
    // 点击其他地方时关闭表情面板
    document.addEventListener("click", hideProver, false);
};
const closePopover = () => {
    // 关闭时移除事件
    document.removeEventListener("click", hideProver, false);
};

const fileLimit = 10;

const uploadRef = ref(null);

/* 点击按钮选择文件上传 */
const uploadFile = (file) => {
    uploadF(file.file)
    // 清空ref里的文件，否则后续再选会把之前选的文件一起上传
    uploadRef.value.clearFiles();
};

import { getFileType } from "@/utils/Constants";

/* 根据文件名获取文件类型 */
const getFileTypeByFileName = (fileName) => {
    const suffix = fileName.substr(fileName.lastIndexOf(".") + 1);
    return getFileType(suffix);
}

/* 上传文件的实际操作 */
const uploadF = (file) => {
    const fileType = getFileTypeByFileName(file.name);
    // console.log("fileName: " + file.name + " fileType: " + fileType)
    sendMsg({
        messageContent: "[" + getFileType(fileType) + "]",
        messageType: "MEDIA",
        filePath: file.path,
        fileName: file.name,
        fileSize: file.size,
        fileType: getFileType(fileType)
    }, false)
}

const showEmojiPopover = ref(false);
const showSendMsgPopover = ref(false);

const hideProver = () => {
    showEmojiPopover.value = false;
    showSendMsgPopover.value = false;
};

const msgContent = ref("");
const sendMessage = (event) => {
    // shift + enter 换行，不发送信息
    if (event.shiftKey && event.keyCode === 13) {
        return;
    }
    event.preventDefault();  // 阻止默认行为，即让回车键不会换行
    const messageContent = msgContent.value.trim();
    if (messageContent == "") {
        // 提示不能发送空白消息
        showSendMsgPopover.value = true;
        return;
    }
    sendMsg({ messageContent, messageType: "TEXT" }, true)  // type 0 普通的聊天消息
};

const emit = defineEmits(["addMessage"])

import { useSysSettingStore } from "@/stores/SysSettingStore";
const sysSettingStore = useSysSettingStore()
const sysSetting = sysSettingStore.getSysSetting()
// console.log(sysSetting)

/* 校验文件大小是否超过了限制 */
const fileSizeExceed = (fileType, fileSize, fileName) => {
    const SIZE_MB = 1024 * 1024;
    let sizeLimit = 0;
    switch (fileType) {
        case "IMAGE":
        case 0:
            sizeLimit = sysSetting.maxImageSize * SIZE_MB;
            break;
        case "VIDEO":
        case 1:
            sizeLimit = sysSetting.maxVideoSize * SIZE_MB;
            break;
        case "OTHER":
        case 2:
            sizeLimit = sysSetting.maxOtherSize * SIZE_MB;
            break;
    }
    if (fileSize > sizeLimit) {
        proxy.Confirm({
            message: `${fileName} 文件大小超过 ${sizeLimit / SIZE_MB}M 大小限制`,
            showCancelBtn: false
        })
        return true
    }
    return false
}

/* 单次校验上传的文件个数是否超过限制 */
const fileCountExceed = (files) => {
    if (files.length > sysSetting.maxFileCount) {
        proxy.Confirm({
            message: `一次最多只能上传 ${sysSetting.maxFileCount} 个文件`,
            showCancelBtn: false
        })
    }
}

/* 最终的发消息的函数，发送信息或者文件等都是调用的这个函数 */
const sendMsg = async (
    messageObj = {
        messageContent,
        messageType,
        filePath,
        fileSize,
        fileName,
        fileType,
    },
    cleanMsgContent) => {
    // 判断文件大小
    if (fileSizeExceed(messageObj.fileType, messageObj.fileSize, messageObj.fileName)) {
        return;
    }
    if (messageObj.fileSize == 0) {
        proxy.Confirm({
            message: `${messageObj.fileName} 文件为空文件`,
            showCancelBtn: false
        })
        return;
    }
    let result = await proxy.Request({
        method: "post",
        url: proxy.Api.sendMessage,
        showLoading: false,
        // 从传入控件的数据中获取要发送的对象等信息
        params: {
            messageContent: messageObj.messageContent,
            messageType: messageObj.messageType,
            contactId: props.currentChatSession.contactId,
            contactName: props.currentChatSession.contactName,
            contactType: props.currentChatSession.contactType == 0 || props.currentChatSession.contactType == 'USER' ? "USER" : "GROUP",
            sessionId: props.currentChatSession.sessionId,
            filePath: messageObj.filePath,
            fileSize: messageObj.fileSize,
            fileName: messageObj.fileName,
            fileType: messageObj.fileType
        },
        showError: false,
        errorCallback: (res) => {
            proxy.Confirm({
                message: res.info,
                okFun: () => {
                    // 失败则弹框重新添加好友
                    addContact(props.currentChatSession)
                },
                okText: '重新申请'
            })
        },
    })
    if (!result) {
        return;
    }
    if (cleanMsgContent) {
        msgContent.value = "";
    }
    // 将消息添加到父组件的消息列表中
    emit("addMessage", result.data)
    // 更新聊天信息列表，保存消息到本地
    result.data.filePath = messageObj.filePath;
    myApi.saveChatMessage(result.data);
}

import SearchAdd from "../contact/SearchAdd.vue";

const searchAddRef = ref();
const addContact = (session) => {
    searchAddRef.value.show({
        contactId: session.contactId,
        contactType: session.contactType
    })
}

/* 拖动文件到发送信息的位置松开后的处理逻辑 */
const dropHandler = (e) => {
    e.preventDefault();  // 阻止默认行为
    // 获取文件列表
    const files = e.dataTransfer.files;
    // 判断文件个数是否超过限制
    if (fileCountExceed(files)) {
        return;
    }
    // 遍历文件列表，发送消息
    for (let i = 0; i < files.length; i++) {
        uploadF(files[i])
    }
};
const dragOverHandler = (e) => {
    e.preventDefault();  // 阻止默认行为
};
/* 粘贴文件到发送信息框 */
const pasteFile = (e) => {
    // 获取粘贴板中的文件列表
    if (!e.clipboardData || !e.clipboardData.items) return;
    let items = e.clipboardData.items;
    // console.log(items);
    for (let i = 0; i < items.length; i++) {
        if (items[i].kind !== "file") {
            continue;
        }
        // 只处理文件信息
        let file = items[i].getAsFile();
        // console.log("file path: ", file.path)
        if (file.path != "") {
            // 复制的是文件，直接上传
            uploadF(file);
        } else {
            // 截图上传path会是空，数据存储在内存中，此时需要去到主进程中读取文件内容(有的截图软件是有自己的缓存路径的，所以也可以不用这个逻辑)
            const fileData = {}
            const imageFile = new File([file], file.name);
            let fileReader = new FileReader();
            // 定义文件读取完成后的操作
            fileReader.onloadend = async function (e) {
                const byteArray = new Uint8Array(e.target.result);
                fileData.byteArray = byteArray;
                fileData.name = imageFile.name;
                // 主进程保存为临时文件
                const result = await myApi.saveClipboardFile(fileData);
                // 发送消息
                sendMsg({
                    messageContent: '[IMAGE]',
                    messageType: "MEDIA",
                    filePath: result.path,
                    fileSize: result.size,
                    fileName: result.name,
                    fileType: "IMAGE"
                })
            };
            // 读取文件
            fileReader.readAsArrayBuffer(imageFile);
        }
    }
};
</script>

<style lang="scss" scoped>
.emoji-list {
    .emoji-item {
        float: left;
        font-size: 23px;
        padding: 2px;
        text-align: center;
        border-radius: 3px;
        margin-left: 10px;
        margin-top: 5px;
        cursor: pointer;

        &:hover {
            background: #ddd;
        }
    }
}

.send-panel {
    height: 200px;
    border-top: 1px solid#ddd;

    .toolbar {
        height: 40px;
        display: flex;
        align-items: center;
        padding-left: 10px;

        .iconfont {
            color: #494949;
            font-size: 18px;
            margin-left: 10px;
            cursor: pointer;
        }

        :deep(.el-tabs_header) {
            margin-bottom: 0px;
        }
    }

    .input-area {
        padding: 0px 10px;
        outline: none;
        width: 100%;
        height: 115px;
        overflow: auto;
        word-wrap: break-word;
        word-break: break-all;

        :deep(.el-textarea_inner) {
            box-shadow: none;
        }

        :deep(.el-input_count) {
            background: none;
            right: 12px;
        }
    }

    .send-btn-panel {
        text-align: right;
        padding-top: 10px;
        margin-right: 22px;

        .send-btn {
            cursor: pointer;
            color: #0796c1;
            background: ■#e9e9e9;
            border-radius: 5px;
            padding: 8px 25px;

            &:hover {
                background: #d2d2d2;
            }
        }

        .empty-msg {
            font-size: 13px;
        }
    }
}
</style>
